Contents: here  is  described  how  you  may  convert the sources with the
          preprocessor commands to true Modula sources.
          This  text should be carefully read right from the beginning to
          its end before struggling with the preprocessor.
          Afterwards you should read the section about your favorite
          compiler in COMPILER.TXT.


Introduction
============

As I have just mentioned in M2LIB.TXT, you will not avoid to work with  a
command line interpreter (shell) in order to translate the library modules
to a format which your Modula compiler will understand.

First  of  all:  you  will  not  find  here any explanations neither how to
install  a  shell nor how to handle with it. Both things are supposed to be
known.  People  who  are not familiar with shells may send me a disk to get
the preprocessed sources. For details see M2LIB.TXT.

Beside  this,  the  following  informations  should be sufficient to you to
both  work with the shells for which some script files are enclosed and to
create  your  own  script files for a different shell. The enclosed scripts
may be regarded as examples.

Each  source file has to be treated with the preprocessor. Of course, it is
possible  to invoke the preprocessor with its necessary parameters for each
file  by  hand;  but regarding at around 200 files this will mean a pain to
you.  For  that  reason  everything  is done automatically by means of some
shell  scripts  (also  known  as  batch files). At this moment you may take
account of the files being distributed in several directories.

At  first,  the  following common explanations of invoking the preprocessor
and  converting  of  one  source file. This description is independend from
the  shell  you are using. Afterwards, the handling with the enclosed shell
scripts will be explained.


Preprocessing one file
======================

Environment variables used in this context
------------------------------------------

First  of all, the programs 'cpp.ttp' and 'x2d1.tos' have to be copied into
a  directory  where  the  environment variable PATH points to, because your
shell  will  look  into these directories for executable files. Having done
this,  you  may  launch these programs by just typing its name (without its
extension).

Furthermore,  the  preprocessor needs the environment variable GNUINC which
points  to  one  or more directories where the preprocessor looks for files
to be included by the command: #include. This is needed for the source file
OSCALLS.IPP  containing  the  command to load OSCALLS.M2H. In case GNUINC
contains several directories, for instance one for the Modula-2 headers
(*.M2H) and one for the C headers (*.H - the preprocessor originally belongs
to the GNU C compiler, and I am using it for both things) the directories
will be separated by commatas (perhaps semicolon will work too); beside this,
you may write the paths - independend from the shell you are using - with the
well known DOS convention, that means, with drive and \, because this
variable will only be examined by the preprocessor.

You just have to copy OSCALLS.M2H into this or one of these directories. It
also  makes  sense to copy the file PORTAB.M2H into this directory although
it may be located somewhere else.

The  environment  variable TMPDIR will only needed in case the shell does not
support  pipes and therefor temporary files have to be created. TMPDIR points
to that directory in which the temporary file may be created.


Invoking the preprozessor
-------------------------
The basic call of the preprocessor from a shell is:

  cpp -undef -P -D<compiler> -imacros <portab.m2h> <infile> <outfile>


The meaning of the parameters in detail:

  -undef    Do not pre-define any non-standard macros (such as atarist)

  -P        Normally  the  preprocessor  will  produce  some lines with
            supplementary  informations for the C compiler. These lines
            are to suppress.

  -D        By means of the option -D you may define a macro. At this place
            it will be used to identify the compiler, e.g. by -DLPRM2
            z.B. durch -DLPRM2

  -imacros  Hereby  a macro file will be read where only the definitions
            are  stored but no output file is created. This is used to read
            the  macro  file PORTAB.M2H, containing all the specific things
            of a given compiler, e.g. by:

              -imacros e:\usr\include\m2\portab.m2h

  <infile>  This  is  the  input file  to  be treated by the preprocessor,
            e.g.: oscalls.dpp. If infile is omitted the preprocessor will
            read from stdin.


  <outfile> This   is   the   output  file  which  will  be  created  from
            by  the  preprocessor  from <infile>. If outfile is omitted the
            preprocessor will write to stdout.


The  output  file  <outfile>  will still contain a lot of empty lines which
were  created  during  the expansion of the macros. Furtermore, the endings
of  each  line  are just closed by a LF due to the UNIX convention instead
of  CR+LF.  Therefor  the  output  file will be treated by the program x2d1
which  compresses subsequent and empty lines to one and cares for the right
line ends. Just call this program by:

  x2d1 < <in> > <out>

That  means,  x2d1  is a so-called filter reading from stdin and writing to
stdout.  If  your  shell supports so-called pipelines, both programs may be
connected  by  a  pipe  (->  |). Piping directly connects the output of the
preprocessor  with  the  input of x2d1. If your shell does not support this
you will have to create a temporary file.


Using mupfel, ksh or bash
=========================

The following section refers to:

mupfel, version >= 1.9999 (from GEMINI)

ksh,    version >= 4.8/1.1

bash,   version >= 1.14.0

I  only  tested  these  versions. Probably, older versions of them will not
work  without  modifications of the scripts. All these shells are available
from  miscellaneous  ftp  servers,  the mupfel from the GEMINI distribution
surely being the most widespread.

All  three  shells  are  using  rather  the  same syntax within their shell
scripts  (extended bourne shell syntax, according to POSIX.2). Therefor the
scripts   are   nearly  identical.  Some  differences  arise at some places
because of some minor bugs or incompatibilities (of the shells).

While  the  mupfel  is  especially fitted for the Atari and runs both under
plain  TOS and also MiNT/MultiTOS (but without job control) the ksh and the
bash are shells ported from UNIX and needing MiNT/MultiTOS.
It   is  always  a  big problem to teach such shells not only to find their
own  shell  scripts but also accept them as executable, if only the name is
given,   just as if it were a normal program. According to the shell and/or
the   version   you   are  using,  some  or all of the following things are
necessary:

1) The shell script must be found in a directory mentioned by PATH because
   the shell will look for executable files within these directories.

2) It  is  possible  that  the shell recognizes its own scripts by certain
   file  extensions;  in  this case the filename is extended for example by
   .mup or .ksh which may be omitted at the invokation.

3) The  first line of the script should begin with #! followed by the name
   of the shell. According to your shell it may be necessary to write its
   full pathname.

4) If  the  script  is  located on a according filesystem, e.g. on a Minix
   partition, the  x-bit  should  be  set  (chmod  +x <script>). This marks
   executable  files  (but  this  will  not  mean  that  they  are  really
   executable; it will be recognized just during loading the file).


If  all this does not help you may type the script with its full path as an
argument of an explicit call of the shell, e.g.:

  ksh /bin/m2pp.ksh <parameter of m2pp.ksh>


I  myself  have  to  ensure  the  following  things to get the preprocessor
script started by typing: m2pp:

o common things:
  - for all three shells 1) is true.
  - none of the three shells need 4), but it does not hurt.
  - environment variables are set by export <variable>=<value>.
    For the preprocessor e.g.:
      export GNUINC="e:\usr\include\m2,e:\usr\include"
  - the environment variable TMPDIR is not needed, as all three shells
    support pipes.

o mupfel:
  at 2): script files are recognized by looking for the extension .mup,
         therefor the script is called m2pp.mup. If you unpack GEMINI you
         will automatically get a directory named SCRIPTS -- you may copy
         m2pp.mup to this directory.

  at 3): '#!mupfel' is necessary as first line. You need not tell the path
         of the mupfel.

  The paths in PATH are given by their DOS notation, this means with \ as
  directory separator and a leading drive specification. Each path is
  separated by a comma or a semicolon. For example:

    export PATH=".;e:\bin;e:\usr\bin"


o ksh:
  at 2): script files are recognized by looking for the extension .ksh,
         therefor the script is called m2pp.ksh.

  at 3): the full path of the ksh is necessary as the first line, for
         example: #!/bin/ksh.

  The paths in PATH are given by their UNIX notation, this means with / as
  directory separator. A drive specification is only possible by the scheme
  /dev/e/ (for e:\), but it makes more sense to use the drive U: as the root
  and to create symbolic links to the "real" directories. That way all paths
  may begin with /. The paths are UNIX-like separated by the colon. Example:

    export PATH=".:/bin:/usr/bin"

  Important: the script is a text file in UNIX format, that means the line
             endings are represented by LF not CR+LF. Reading a wrong line
             end Ksh will put out a syntax error.

o bash:
  at 2): there are no special extensions for script files, for that reason
         the script is simply named m2pp.

  at  3): A #!bash is sufficient for the first line. The path does not need
          to be made known

  The same as said at the bash is true for the paths in PATH.

  Important: the script is a text file in UNIX format, that means the line
             endings are represented by LF not CR+LF. Reading a wrong line
             end Bash will put out a syntax error.


As I said before, the script is rather identical for all three shells.
In the following I will refer to the mupfel's version which rather does
not make a difference (the paths are given in different way).


Using m2pp
----------

At  first,  some  minor  things  have to be fitted to your environment. For
that  reason  the  function setup() is defined just at the beginning of the
script where these fittings are done by setting shell variables.

In detail:

o The variable def_macros has to be set to the full path of the macro file
  PORTAB.M2H. For example:

    def_macros=e:\usr\include\m2\portab.m2h

o According to your compiler the source files have different extensions
  for definition-, implementations- and program modules. At run time the
  current compiler definition will determine them by setting the variables
  m2_def, m2_imp and m2_mod to the according values. These extensions are
  just correct for all systems in their standard configuration.
  You just may change them for some systems (HM2, MM2), and then you have
  to change m2pp, too. But normally this is not necessary.

o Furthermore you may declare the extensions of the original source texts
  - the text files with the preprocessor commands. Normally, these are dpp,
  ipp and mpp. So you need not change anything, here. If you like to use
  different extensions, you will have to set the variables cpp_def, cpp_imp
  and cpp_mod accordingly.

In the most cases it is only necessary to set def_macros.
Saving the file you have strictly pay attention to the line ends with LF's
only.


Calling the script by: m2pp -h (for help) the following text will appear:

  Aufruf: m2pp [OPTIONEN] compiler destdir

   -d dir         All files in the directory <dir>
   -s dir         All files in all subdirectories of <dir>
   -f file        Only file <file>
   -m macros      use <macros> instead of the default PORTAB.M2H
   -q             no messages except those of the preprocessor
   -h             This text

  M2-files with preprocessor commands are translated to pure M2-files.
  One of the following constants may be set for <compiler>:
  LPRM2, SPCM2, TDIM2, MM2, HM2.
  The options -s, -d and -f are mutual exclusive. Without one of these
  options all files within the current directory are treated.
  Options must not be grouped and arguments have to be separated from the
  option by a space character.


This  just leads to the application. Supposing that M2LIB has been unpacked
in  the  root  directory  of drive e:, the Modula-2 files shall be put into
the  directory  m2lib  of the drive m: and the whole thing shall be created
for the LPR compiler, the following steps will be necessary:

Preprocessing of the POSIX modules by:

  m2pp -s e:\m2lib\source\posix LPRM2 m:\m2lib

According for the ISO modules:

  m2pp -s e:\m2lib\source\iso LPRM2 m:\m2lib

The modules of MISC are not to be found within subdirectories:

  m2pp -d e:\m2lib\source\misc LPRM2 m:\m2lib

As  explained  towards  the  end  of this text under 'tips and tricks', you
should  not  preprocess  all  files  at  one time, but first translate each
library before starting with the next one.

If  you  like to preprocess a single file, as for example necessary for the
LPR  compiler  with  the module 'DosSystem', a call by the following way will
be suitable:

  m2pp -f e:\m2lib\source\posix\dossyste.ipp LPRM2 m:\


According  to  the  libraries the test modules which are not located within
subdirectories may be preprocessed:

  m2pp -d e:\m2lib\test\posix LPRM2 m:\m2lib
  m2pp -d e:\m2lib\test\iso LPRM2 m:\m2lib
  m2pp -d e:\m2lib\test\misc LPRM2 m:\m2lib

You  may  try  some more options for m2pp, if you like. The script makes,
as far  as possible, some security checks. So, error messages may also
appear, but they are self explaining.


Using the gulm shell
=====================

This  shell  is  not  yet  the  state  of  the  art  since a long time, but
nevertheless  it  is  perhaps  still  used  by  many  people  (by  me  too,
sometimes),  because  it  was  one  of  the first to allow a certain ``UNIX
feeling''.


The  script  files are kept as simple as possible. Only the shell's ability
to  call  script files with parameters (out of other script files, too), to
redirect  input  and  output and to set environment variables is used. This
has  the  advantage that you practically may adapt the scripts to any other
shell,  on  the  other side any security checks are dropped. So, it is easy
to  make  a  mistake when calling the scripts (sleeping for a little moment
and suddenly a source text is lost -- it just has happened to me).

Executable  scripts  are recognized by the extension .g and must be located
within  a  directory  mentioned  by  PATH.  They are started without typing
their  extensions.  Contrary to the UNIX shell described above, the scripts
are  not  executed  by  a  new  instance of the shell but always by the one
existing.  This  is  the reason why scripts may be nested without loosing a
remarkable  part  of memory. Within the directory BIN\GULAM you will find a
lot  of  scripts  not  all  being  needed but for the first, they should be
copied into a separate directory mentionned by PATH.

You better set the following variables within the startup file GULAM.G:

  set path '.,e:\usr\bin,e:\bin'

After  a  'set  path' gulm will automatically set the environment variable
PATH. Of course, the right paths are to be adapted to your own system.

Environment  variables  are  set  by the command setenv <variable> <value>.
For GNUINC it will look like for example:

  setenv GNUINC e:\usr\include\m2,e:\usr\include

As gulm does not support pipes TMPDIR has to be set, too, e.g.:

  setenv TMPDIR e:\tmp


As  I said before, it is quite easy to nest the scripts. A fact that I have
widely  used.  The  "kernel script" is m2ppx.g which just only preprocesses
one source text using the commands described at the beginning of this file.
The call is:

  m2ppx <compiler> <infile> <outfile>

<compiler>  identifies  the  compiler  to  be  used.  It  may be one of the
following identifiers: LPRM2, HM2, MM2, TDIM2, SPCM2.
<infile> is the input file with the preprocessor commands and
<outfile> is the resulting Modula source text.
In  this  script  the  path to the macro file PORTAB.M2H has to be adapted,
e.g.:

  -imacros e:\usr\include\m2\portab.m2h


This script may be used to preprocess a single file, for example the
'DosSystem' which is additionally needed for the LPR compiler:

  m2ppx LPRM2 e:\m2lib\source\posix\dossyste.ipp m:\dossysste.mod

To  convert  multiple  files  at  one  time  this  script  has to be called
automaticallay  for  all  desired  files.  This  is the task of the scripts
x_m2.g, iso_m2.g, misc_m2.g, tx_m2.g, tiso_m2.g and tmisc_m2.g.

The first three  scripts  preprocess  the  libraries  while  the others are
responsible for the the test modules. It is important for all these scripts
to change first into the upper directory of each library before calling the
script, sofor example the actual directory has to be ...\SOURCE\POSIX when
calling x_m2, and ...\TEST\POSIX when calling tx_m2.

The parameters for the library scripts:

  *_m2 <compiler> <destdir> <def-ext> <imp-ext>

The parameters for the test scripts:

  *_m2 <compiler> <destdir> <mod-ext>

<destdir>  is  the  directory  where the converted modules should be moved,
<def-ext>  is  the  extension  for  definition  modules,  <imp-ext>  is the
extension  for  implementation  modules  and <mod-ext> is the extension for
program modules.

Supposing,  M2LIB  has been unpacked within the root directory of drive e:,
the  Modula-2  files  shall be moved to the directory m2lib of drive m: and
the  whole  thing shall be created for the LPR compiler, then the following
steps will lead to success:

  cd e:\m2lib\source\posix
  x_m2 LPRM2 m:\m2lib def mod

  cd e:\m2lib\source\iso
  iso_m2 LPRM2 m:\m2lib def mod

  cd e:\m2lib\source\misc
  misc_m2 LPRM2 m:\m2lib def mod

for the library modules, and

  cd e:\m2lib\test\posix
  tx_m2 LPRM2 m:\m2lib mod

  cd e:\m2lib\test\iso
  tiso_m2 LPRM2 m:\m2lib mod

  cd e:\m2lib\test\misc
  tmisc_m2 LPRM2 m:\m2lib mod

for the test modules.

As  explained  under  'tips'  towards  the  end of this text you should not
preprocess  all  files  at one time but first translate each library before
starting with the next one.

If  you  want  to  omit  the  parameters  of  this  script  or to exclude a
potential  source  of  errors you may write other scripts consisting simply
of a call with the appropriate parameters.

A  script  to  preprocess  the  POSIX  modules  for LPR might look like the
following:

      name: XLPR.G
  contents: x_m2 LPRM2 m:\m2lib def mod

This  is  just  the  task  of all the other script files in BIN\GULAM. They
only  serve as an example. At least you have to fit the output path to your
own  situation.  The  name  of  these  scripts should content a hint to the
compiler or the library they are tought to be used for.


Changing the configuration
==========================

Within  the  file  PORTAB.M2H  you may switch some settings influencing the
Modula  source  text  globally  by setting certain compiler options. Hereby
the following macros are defined just at the beginning of the file:

  #if 0
  #define __RES_ON_STACK__
  #endif

  #if 1
  #define __LONG_WHOLE__
  #endif

  #if 0
  #define __LONG_REAL__
  #endif

  #if 1
  #define __REG_VARS__
  #endif

  #if 0
  #define __RANGE_CODE__
  #endif

  #if 0
  #define __STACK_CODE__
  #endif

  #if 0
  #define __DEBUG_CODE__
  #endif

The  setting  of these macros may be changed if you like. Above you see the
default  setting.  If  the  condition  within  the #if and #endif clause is
equal  to  0  the macro will be undefined otherwise it will be switched on.
If  a  compiler  does  not  support the corresponding option the macro will
have  no  meaning.  If  the  option  is  only to be set before starting the
compiler  but  not  within  the source text, this macro must (!) correspond
with  the  global compiler setting. But if the option may be set within the
source  file  it  will  automatically  be  set  together  with  other basic
settings depending from this macro.

The meaning of the macros is as follows:

  __RES_ON_STACK__:
  The results of functions will be returned on the stack else within
  registers (D0/D1). The return within registers is default.

  __LONG_WHOLE__:
  The types CARDINAL and INTEGER are identical to LONGCARD and
  LONGINT, that means the biggest whole number type, according to the
  ISO, else with SHORTCARD and SHORTINT. Per default identical to the
  LONG types.

  __LONG_REAL__:
  The typ REAL is identical with LONGREAL else to SHORTREAL.
  Per default identical to SHORTREAL.

  __REG_VARS__:
  Local variables with the attribute __REG__ are declared as
  register variables else they are not. Activated by default.

  __RANGE_CODE__:
  If the macro __DEBUG__ appears within the source text all compiler
  options for creating index and range tests or something like that
  will be switched on or off, respectively. Switched off by default.

  __STACK_CODE__:
  As above but it will concern the creation of stack tests.
  Switched off by default.

  __DEBUG_CODE__:
  As above but it will concern the creation of additional code to support
  debuggers. Switched off by default.


By  the way, you generally should leave the stack test switched off as same
as  the debug and the range check code because it may lead to some errors -
dependend from your compiler.

Another setting is only of concern for the Megamax compiler. If version 4.3c
is used, the macro MM2_43c must be avtivated by changing the 0 into a 1,
otherwise some modules cannot be compiled due to a compiler error with
value constructors.

  #if 0 && (defined MM2)
  #  define MM2_43c
  #endif


It  may  be  necessary  to  change some more settings, first of all for the
Hnisch  compiler:  recently,  some  ISO  features have been built in to be
respected  by certain (ISO_*) macros. Which of them these are is to be read
in COMPILER.TXT.
The  default  setting  is  appropriate to my own compiler version. I cannot
tell  you  which  version supports which features. Try it yourself. For the
sake of safety you may switch off all macros mentioned in COMPILER.TXT.


Beside  of the settings in PORTAB.M2H you may set some more things directly
within  the  modules. The configuration is done in the same way by defining
certain  macros  at  the beginning of the file or not. Hereby the condition
within the #if and #endif clause has to be set to 1 or 0.

The following macros exist:

macroname                       module(s)

__OSCALLS__                     OSCALLS

  Defining this macro will just only lead to the omitting of the stack
  correction for some compilers, after a operating system call, because
  this is done automatically at the end of a procedure. This macro will
  be evaluated within OSCALLS.M2H and it should normally be exclusive for
  the module OSCALLS.


LPR_LTL_MTERM                   DosSystem

  As  described  in  COMPILER.TXT  you  have  to create two versions of the
  module 'DosSystem' for the LPR  compiler  because  the module termination
  is basicly different between the shell and linked programs.
  The macro is to be defined for the shell not for linked programs.


__USE_SYSBASE_FOR_BASEPAGE__    DosSystem

  With  this  macro  you  may  set  wether  the value of the variable BASEP
  is determined at program start by means of a system specific  module  or
  by means of the function "ActBasepage()". The system specific modules
  mostly return that value which is pushed onto the stack at program's start
  as a paramter whereas "ActBasepage()" determines its value by a system
  variable or a GEMDOS call if available. There should be no difference
  between the two methods although the first one is more usual.


__USE_AES_FOR_ARGV0__           args

  Normally,  the  zero'th  argument  of  the  command  line  of  a  program
  (argv[0]),  with  or  without  full path, is expected to be the program's
  name. If the ARGV method (which is a new ATARI standard) is used to start
  a  program  the  zero'th argument may be pushed without any problems. The
  MultiTOS  desktop  uses  this feature. The SingleTOS desktop does not use
  this   method,  so the propram's name cannot be recognized. By activating
  this  macro  the  AES  function shel_read is used to try to determine the
  program's   name  but  it  does not always work. In order to do the
  shel_read call, the program registers itself for a short time at the AES.
  The AES functions are suited to the GEM library "crystal". This macro is
  not avtivated by default.


__NO_IO_EXCEPTIONS__            DeviceSupport, RndFile, SeqFile, StreamFile

  The  compilers  supported  by  this  library are not able to generate ISO
  exceptions.  Unfortunately, errors  within  the  IO  library  may only be
  reported  by exceptions. In this implementation an exception will lead to
  a       termination   of  the  program; as this is commonly not a welcome
  reaction  on an  error  due  to  underlaying  operation system functions,
  e.g.  missing  access rights or an overfilled disk drive, you may install
  here  that no exceptions will be generated by such errors but only set an
  error   code  which may be inquired by the function "DeviceError()" after
  an IO operation. Logical errors such as trying to write to a channel only
  opened  for  reading  will lead to exceptions and so to the ending of the
  program  as  these  are  programmer's  errors. This macro is activated by
  default.


__NO_EXCEPTIONS__               RealMath, LongMath, RealXMath, LongXMath,
                                ComplexLib, LongComplexLib

  Errors  within  arguments of mathematical functions will normally lead to
  exceptions.  With  this  macro  you  may install that a adequate function
  value  will  be  returned  rather than an exception. As errors within the
  arguments  commonly are programmer's errors this macro is switched off by
  default.

The  macros __IO_EXCEPTIONS__ and __NO_IO_EXCEPTIONS__ should each have the
same value within all the different modules.


__EXP_PLUS_SIGN__               FConvBase
__EXP_UNDERFLOW__
__NO_LEADING_DIGITS__
__ONLY_EXP__

  By   means  of  this  macro  you  may control a little bit the conversion
  between  (LONG)REAL  numbers  and strings. With __EXP_PLUS_SIGN__ you may
  install  wether a positiv exponent will get a sign during its conversion;
  unfortunately,  the  ISO is misunderstanding at this point. By default a
  sign will be produced. By means of __EXP_UNDERFLOW__ you may install that
  a  conversion  into  a too small number will generate an exception rather
  than       returning     simply   zero   as  it  is  the  case  with ISO.
  With   __NO_LEADING_DIGITS__   and   __ONLY_EXP__   you   may  unlock the
  syntax  of  a  correct  string a little bit; in this case numbers without
  leading  digits before the decimal point or numbers consisting only of an
  exponent  will  be  accepted.  As  this  is  not  true ISO the macros are
  switched off by default.


__CHECKS__                      RBTrees, DLists, Queues, Stacks, mem

  With this macro you may decide wether to provide the security checks at
  run time. A check wether the pushed ADT is well defined and wether the
  size of its elements corresponds  with their  definition  belongs to
  this option. These inquiries provide an additional  security during the
  development time and may be removed within  the final  program.  This
  macro is activated by default.


_DEBUG                          RBTrees, DLists, mem

  This macro has its only meaning  for  the  test  of the modules. If set,
  code will be produced for some test procedures. This macro should be
  switched off in your own programs. Per default it is not activated.


__MAGICLIB_TERM__               DosSystem

  This macro is only of concern for those who use Peter Hellingers
  MagicLib 4.x together with M2LIB. If set, the main process unregisters
  itself correctly from the Magic kernel when calling "exit()" or "Exit()".
  This macro is not avtivated by default.


__THREADSAFE__                  mem

  If set, memory allocations from concurrently running threads are handled
  correctly. For this threads must register and unregister itselfs at
  the storage management. This macro is activated by default.


__USE_MEM__                     pSTORAGE

  If set, module 'pSTORAGE' uses module 'mem' for storage management,
  otherwise a M2 system specific module. This macro is not activated by
  default.


__INCLUDE_DE_LOCALE__           loc
__INCLUDE_EN_LOCALE__
__INCLUDE_FR_LOCALE__
__INCLUDE_NL_LOCALE__

  If set, it's possible to activate the corresponding locales at runtime.
  But every locale increases program size. Only the German locale (DE) is
  activatable by default.


Normally,  the settings both the global ones and also the local ones within
the modules need not be changed because their default values make sense. If
you change a set you should know its effects.


Messages of the preprocessor
============================

The  preprocessor  may output some messages during processing. The messages
should  be  self-explaining  and  do not mean any harm to you but they will
inform you about some special things of the chosen compiler.

The following messages may occur:

dossyste.ipp:#warning This version of DosSystem only suitable for load-time-linking!
dossyste.ipp:#warning You need 'LPRTERMINATION' and the new 'GEMX'
dossyste.ipp:#warning You need 'CleanUp'
dossyste.ipp:#warning ...using M_Appl.ApplTerm for program termination
dossyste.ipp:#warning ...using _sysbase for determining the Basepage address
mem.ipp:#warning Storage allocation is not thread save!
args.ipp:#warning ...using AES for argv[0]
pstorage.ipp:#warning ...using 'mem' for storage allocation
pstorage.ipp:#warning ...using M2-system storage allocator

Beside  this, the preprocessor itself may produce some more error messages,
in  most  cases caused by a macro file which may not be found. In this case
the  paths (for PORTAB.M2H at -imacros, and for OSCALLS.M2H in GNUINC) have
to be corrected.


Installation
============

The  basic  installation  that  means  the  translation of the preprocessed
modules  by  the  compiler  and  making  known the translated files to your
system   by   search   paths  is  system  dependend  and  is  described  in
COMPILER.TXT or in the manual of your Modula-2 system, respectively.


Tips and tricks
===============

o The speed of preprocessing may be increased if often used files lie on a
  Minix  filesystem (under MiNT or MultiTOS, respectively) as operations on
  directories (especially in our case the opening of files) run faster here
  than   on a TOS filesystem. You may easy determine it yourself by running
  the   test     program   "tfile"   both  on  a  TOS  filesystem  and on a
  Minix  filesystem;   in   the  latter  case  the program mainly creating,
  opening  and  deleting  files  will  really  run  faster.  At  least  the
  preprocessor and x2d1 should be found on a  Minix filesystem, perhaps the
  header file PORTAB.M2H, too.

  A  further  acceleration  will  be  possible if at least the MiNT version
  1.10h4 is used: as both the preprocessor and x2d1 have been compiled with
  the   "shared  text"  attribute  (GNU-C option -mbaserel) you may set the
  "sticky   bit"  as  a  file  attribute  on  a Minix filesystem by doing a
  chmod +t <file>. This way the text segment of these programs will be read
  only  once  into the memory and it will be used for the following program
  calls (if it is  not removed because of lack of memory in the meantime).

o Because  of  the  lot  of  files  you  are  recommended to translate the
  libraries one after the other. That means you preprocess the source files
  of  the  POSIX directory at first and then put the resulting source files
  into  the  compile  directory.  These  files are compiled by means of the
  compiler   specific   batch  files  and  then the object files are copied
  into  the  according  directory.  After  this  all  files  of the compile
  directory  may be removed. The same thing happens to the files of the ISO
  directory  and  the  MISC  directory.  The POSIX modules make the largest
  part  of  the  files; 1.0 to 1.5 MB are necessary to keep both the source
  files  and  the  object files within one directory. If you use a RAM disk
  you  will  have to care for a sufficient amount of free RAM otherwise you
  have to use a directory of your hard disk.

o Some Modula compilers (Hnisch and Megamax) allow the use of underscores
  ('_') within identifiers, other do not. The original C identifiers of the
  POSIX modules use a lot of underscores ('uid_t') which I have replaced by
  changing  its names ('uidT') to allow the use of all the other compilers.
  If  you  want, you may use the original names; for this purpose there is
  a   macro  file  named  C_ID.M2H which defines the changed
  identifiers by  their original names, e.g.:

    #define uidT uid_t

  The  easiest  way  to  make  this  conversion  is  directly  during  the
  preprocessing.  In  addition to the macro file PORTAB.M2H simply read the
  file  C_ID.M2H. There is only the need of a further option within the
  command line of the preprocessor; you just have to add

    -imacros <full path of the file C_ID.M2H>

  into the script file of your commandline interpreter.

  But   it   is  also  possible to do this conversion at any later time. It
  will  be  necessary  to  run the preprocessor a second time but using the
  macro  file  C_ID.M2H  instead  of PORTAB.M2H. Beside the name of the
  macro  file  the  extensions  of  the  source  files  have  to  be edited
  within  your shell script,  because  their  extensions  are  not .dpp and
  .ipp (but .def and .mod, for example).

  A   further  macro file named M2_ID.M2H defines the names into the "other
  direction".   So, it  is also possible to come from the original names to
  the  changed  identifiers;  for  this  purpose  there  is  a  need  of an
  additional  preprocessor  run with the according changes within the shell
  script as described above.

o At  some  places of the M2LIB documentation the GEM library "crystal" is
  mentioned.  This  library  makes  use  of  M2LIB  at some places, exactly
  spoken,  it  makes  use of some modules of the POSIX library. This may be
  switched  off  (by  macro).  Beside  this  both crystal and M2LIB use two
  identical  modules:  PORTAB and pSTORAGE. If you want to use both crystal
  and  M2LIB  you  should  go  ahead in the following way in order to avoid
  version  conflicts:  at  first you have to translate all modules of M2LIB
  (or  only  the  POSIX modules, respectively), then you may preprocess and
  compile   the   modules  of  crystal but without PORTAB and pSTORAGE. You
  have  to omit the compilation of the POSIX modules altough there are some
  batch files for it.

  As   mentioned  some  more  above you may determine the program's name by
  ShelRead  within  'args'.  In  this  case some functions of crystal are
  used.   If   you  want  this   you   will   work   just  in  that  order
  as described  above  but  omitting  the compilation of the implementation
  module  of  'args'.  This one may be compiled separately at last, after
  having compiled the rest of crystal.

